<?php

namespace app\admin\services;

use app\admin\model\ExpressModel;
use app\admin\model\LogModel;
use app\admin\model\MainBodyModel;
use app\admin\model\OrderHistoryModel;
use app\admin\model\OrderInModel;
use app\admin\model\ShopModel;
use Complex\Exception;
use think\facade\Queue;
use think\facade\Validate;

class NewOrderService extends BaseService
{

    /**
     * 订单处理任务
     * @param $p
     * @return array
     */
    public static function handle($p){
        $rule=[
            'type'=>'require',
            'timestamp'=>'require',
            'sign'=>'require',
            'data'=>'require',
        ];
        $validate=Validate::rule($rule);
        if(!$validate->check($p)){
            return [
                'errno'=>1,
                'msg'=>$validate->getError(),
                'data'=>[]
            ];
        }
        switch ($p['type']){
            case 'refund_status':
                $res=self::refundStatus(json_decode($p['data'],true),$p['log_id']);
                break;
            case 'order_package':
//                $res=self::orderPackage(json_decode($p['data'],true),$p['log_id']);
                $res=new \stdClass();
                break;
            default:
                $res=self::orderStatus(json_decode($p['data'],true),$p['log_id']);
        }
        return $res;
    }

    /**
     * 订单即刻处理
     * @param $p
     * @return void
     */
    public static function inNow($p){
        $res=self::handle($p);
        api_return_baidu($res['errno'],$res['msg'],$res['data']);
    }

    /**
     * 订单队列处理
     * @param $p
     * @return void
     */
    public static function inQueue($p){
        $isPush=Queue::push('app\admin\job\OrderNewDismiss',json_encode($p),'pushNewOrders');
//        $isPush=Queue::later(10,'app\admin\job\OrderNewDismiss',json_encode($p),'pushNewOrders');
        if($isPush) {
            api_return_baidu();
        }
        else{
            api_return(500,'defeat');
        }
    }

    /**
     * 订单状态变更
     * @param $data post请求数据
     * @param $log_id 日志id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected static function orderStatus($data,$log_id){
        $rule=[
            'orderId'=>'require',
            'appId'=>'require',
            'shopId'=>'require',
            'ucid'=>'require'
        ];
        $validate=Validate::rule($rule);
        if(!$validate->check($data)) {
            return [
                'errno'=>1,
                'msg'=>$validate->getError(),
                'data'=>[]
            ];
        }
        if($data['orderId']=='1234567890') {
            return [
                'errno'=>0,
                'msg'=>null,
                'data'=>[]
            ];
        }
        $url='https://api.baidu.com/json/sms/service/PlatOrderBusinessQueryService/getOrderDetail';
        $shopInfo=ShopModel::where([['shop_id','=',$data['shopId']]])->field('username,mainbody_id,area,shop_id,accesstoken')->find();
        if(empty($shopInfo->mainbody_id)||empty($shopInfo->accesstoken['accessToken'])) {
            LogModel::editWithReturn(['id'=>$log_id,'done'=>3,'res'=>['error'=>1,'msg'=>'shop not bind']]);
            return [
                'errno'=>1,
                'msg'=>'shop not bind',
                'data'=>[],
            ];
        }
        $params=[
            'header'=>[
                'userName'=>$shopInfo->username,
                'accessToken'=>$shopInfo->accesstoken['accessToken'],
            ],
            'body'=>[
                'orderId'=>$data['orderId'],
                'ucid'=>$data['ucid'],
                'shopId'=>$data['shopId'],
                'appId'=>5
            ]
        ];
        $header=[
            'Content-Type: application/json'
        ];
        $res=json_decode(post($url,json_encode($params),$header),true);

        if($res['header']['desc']=='success') {
            $orderInfo=self::handleOrderSatus($res['body']['data'][0], $shopInfo,1);
            $orderInfo['log_id']=$log_id;
            //订单状态为已完成，最后一次更新物流状态详情
//            if($res['body']['data'][0]['orderStatus']==7) {
//                $expressRes = ExpressService::getExpressInfoFromBaidu($shopInfo->username, $shopInfo->accesstoken['accessToken'], $data['orderId'], $data['shopId']);
//                if (!empty($expressRes['body']['data'][0])) {
//                    $orderInfo['express_detail'] = $expressRes['body']['data'][0]['packageDetails'][0]['expressDetailInfoList'];
//                }
//            }
            try {
                $done=(OrderInModel::editWithReturnWithoutDelete($orderInfo))?1:2;
                LogModel::editWithReturn([
                    'done' => $done,
                    'id' => $log_id,
                    'res'=>$res
                ]);
                return [
                    'errno'=>0,
                    'msg'=>null,
                    'data'=>[],
                ];
//                api_return_baidu();
            }catch (\Exception $e)
            {
                return [
                    'errno'=>1,
                    'msg'=>$e->getMessage(),
                    'data'=>[]
                ];
            }
        }else {
            LogModel::editWithReturn(['id'=>$log_id,'res'=>$res]);
            return [
                'errno'=>1,
                'msg'=>'something error',
                'data'=>['body'=>$params,'res'=>$res['header']['failures']]
            ];
        }
    }

    /**
     * 售后状态变更
     * @param $data post请求数据
     * @param $log_id 日志id
     * @return array
     */
    protected static function refundStatus($data,$log_id){
        $rule=[
            'orderId'=>'require',
            'appId'=>'require',
            'shopId'=>'require',
            'ucid'=>'require'
        ];
        $validate=Validate::rule($rule);
        if(!$validate->check($data))
        {
            return [
                'errno'=>1,
                'msg'=>$validate->getError(),
                'data'=>[]
            ];
        }
        $url='https://api.baidu.com/json/sms/service/PlatBusinessOrderRefundService/queryOrderRefundInfo';
        $shopInfo=ShopModel::where([['shop_id','=',$data['shopId']]])->field('username,mainbody_id,area,shop_id,accesstoken')->find();
        if(empty($shopInfo->mainbody_id)) {
            LogModel::editWithReturn(['id'=>$log_id,'done'=>3,'res'=>['error'=>1,'msg'=>'shop not bind']]);
            return [
                'errno'=>1,
                'msg'=>'shop not bind',
                'data'=>[]

            ];
        }
        if(empty($shopInfo->accesstoken['accessToken'])){
            LogModel::editWithReturn(['id'=>$log_id,'done'=>3,'res'=>['error'=>1,'msg'=>'token error']]);
            return [
                'errno'=>1,
                'msg'=>'token error',
                'data'=>[]

            ];
        }
        $params=[
            'header'=>[
                'userName'=>$shopInfo->username,
                'accessToken'=>$shopInfo->accesstoken['accessToken'],
            ],
            'body'=>[
                'refundId'=>$data['refundId'],
                'ucid'=>$data['ucid'],
                'shopId'=>$data['shopId'],
                'appId'=>5
            ]
        ];
        $header=[
            'Content-Type: application/json'
        ];
        $res=json_decode(post($url,json_encode($params),$header),true);
        if($res['header']['desc']=='success') {
            $orderInfo=[
                'order_refund_info'=>$res['body']['data'][0],
                'order_id'=>$data['orderId'],
                'refund_type'=>$res['body']['data'][0]['refundType']
            ];
            if(!empty($res['body']['data'][0]['applyTime']))
            {
                $orderInfo['refund_apply_time']=date('Y-m-d H:i:s',strtotime($res['body']['data'][0]['applyTime']));
            }
            try {
                $done=(OrderInModel::updateRefund($orderInfo))?1:2;
                LogModel::editWithReturn([
                    'done' => $done,
                    'id' => $log_id,
                    'res'=>$res
                ]);
                return [
                    'errno'=>0,
                    'msg'=>null,
                    'data'=>[]
                ];
            }catch (\Exception $e)
            {
                LogModel::editWithReturn(['id'=>$log_id,'done'=>3,'res'=>['error'=>1,'msg'=>$e->getMessage()]]);
                return [
                    'errno'=>1,
                    'msg'=>$e->getMessage(),
                    'data'=>[]
                ];
            }
        }else {
            LogModel::editWithReturn(['id'=>$log_id,'res'=>$res]);
            return [
                'errno'=>1,
                'msg'=>'something error',
                'data'=>['body'=>$params,'res'=>$res['header']['failures']]
            ];
        }
    }

    /**
     * 物流状态更新推送
     * @param $data
     * @param $log_id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected static function orderPackage($data,$log_id)
    {
        $rule = [
            'orderId' => 'require',
            'appId' => 'require',
            'shopId' => 'require',
            'ucid' => 'require'
        ];
        $validate = Validate::rule($rule);
        if (!$validate->check($data)) {
            return [
                'errno' => 1,
                'msg' => $validate->getError(),
                'data' => []
            ];
        }
        $orderItem = OrderInModel::find($data['orderId']);
        if(!$orderItem){
            LogModel::editWithReturn(['id' => $log_id, 'done' => 3, 'res' => ['error' => 1, 'msg' => 'order not found']]);
            return [
                'errno' => 1,
                'msg' => 'order not found',
                'data' => []
            ];
        }
        $shopInfo = ShopModel::where([['shop_id', '=', $data['shopId']]])->field('mainbody_id,username,area,accesstoken')->find();
        if (empty($shopInfo->mainbody_id)) {
            LogModel::editWithReturn(['id' => $log_id, 'done' => 3, 'res' => ['error' => 1, 'msg' => 'shop not bind']]);
            return [
                'errno' => 1,
                'msg' => 'shop not bind',
                'data' => []

            ];
        }
        if (empty($shopInfo->accesstoken['accessToken'])) {
            LogModel::editWithReturn(['id' => $log_id, 'done' => 3, 'res' => ['error' => 1, 'msg' => 'token error']]);
            return [
                'errno' => 1,
                'msg' => 'token error',
                'data' => []

            ];
        }
        $expressList = ExpressModel::column('*', 'title');
        $res = ExpressService::updateExpressInfoByOrderId($orderItem, $expressList, $shopInfo->username, $shopInfo->accesstoken['accessToken']);
        LogModel::editWithReturn(['id' => $log_id, 'done' => ($res['errno']) ? 3 : 1, 'res' => $res['data']]);
        return $res;
    }

    /**
     * 度小店应用回调地址
     * @param $p
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function callback($p){
        $rule=[
            'appId'=>'require',
            'authCode'=>'require',
            'state'=>'require',
            'userId'=>'require',
            'timestamp'=>'require',
            'signature'=>'require',
        ];
        $validate=Validate::rule($rule);
        if(!$validate->check($p)){
            api_return(500,'params error');
        }
        if(!$mainInfo=MainBodyModel::where([['appid','=',$p['appId']]])->find())
            api_return(500,'app not register');
        if(!$shopInfo=ShopModel::where([['user_id','=',$p['userId']]])->find())
            api_return(500,'shop not register');
        if(self::getAccessToken($p['appId'],$p['authCode'],$mainInfo->secretkey,$p['userId'],$shopInfo))
            api_return(200,'authorization success');
    }

    /**
     * 签名校验
     * @param $p
     * @param $sign
     * @param $secretKey
     * @return void
     */
    protected static function signatureValidation($p,$sign,$secretKey){
        unset($p['signature']);
        asort($p);
        $str2=base64_encode(json_encode($p));
        openssl_encrypt($str2,OPENSSL_CIPHER_AES_128_CBC,$secretKey);

    }

    /**
     * 获取accesstoken
     * @param $appId 注册应用的appid
     * @param $authCode 回调地址携带参数
     * @param $secretKey 秘钥
     * @param $userId 回调地址携带参数
     * @param $shopModel 店铺model
     * @return void
     */
    protected static function getAccessToken($appId,$authCode,$secretKey,$userId,$shopModel){
        $url='https://u.baidu.com/oauth/accessToken';
        $data=[
            'appId'=>$appId,
            'authCode'=>$authCode,
            'secretKey'=>$secretKey,
            'grantType'=>'auth_code',
            'userId'=>$userId
        ];
        $header=[
            'Content-Type: application/json'
        ];
        $res=json_decode(post($url,json_encode($data),$header));
        if($res->code){
            api_return(500,'',$res);
        }else{
            $shopModel->accesstoken=$res->data;
            return $shopModel->save();
        }

    }

    /**
     * 刷新accesstoken
     * @param $appId
     * @param $refreshToken
     * @param $secretKey
     * @param $userId
     * @param $shopModel
     * @return void
     */
    public static function refreshAccessToken($appId, $refreshToken, $secretKey, $userId, $shopModel){
        $url='https://u.baidu.com/oauth/refreshToken';
        $data=[
            'appId'=>$appId,
            'refreshToken'=>$refreshToken,
            'secretKey'=>$secretKey,
            'userId'=>$userId
        ];
        $header=[
            'Content-Type: application/json'
        ];
        $res=json_decode(post($url,json_encode($data),$header));
        if(empty($res->data))
            return false;
        else {
            $shopModel->accesstoken = $res->data;
            return $shopModel->save();
        }
    }

    /**
     * 处理订单详情数据结构
     * @param $item
     * @param $shop 数据库查询的shop单条数据，至少包含字段shop_id,username,area
     * @return int|string
     */
    public static function handleOrderSatus($item,$shop,$ucname=2){
        $orderStatus = config('orderStatusMap')['exchange'];
        if (!empty($item['orderDetailNew'])) {
            $detail = $item['orderDetailNew'];
        } elseif (!empty($item['orderDetail'])) {
            $detail = $item['orderDetail'];
        } else {
            $detail = $item['orderPackageInfos'][0];
        }
        $orderInfo = [
            'create_time' => date('Y-m-d H:i:s', strtotime($item['createTime'])),
            'order_id' => $item['orderId'],
            'status' => $orderStatus[$item['orderStatus']],
            'total_amount' => $item['orderTotalAmount'] * 100,
            'shop_id' => $shop['shop_id'],
            'ucid' => $item['ucId'],
            'pay_type' => $item['orderType'],
            'payment_amount' => $item['paymentAmount'] * 100,
            'shop_name' => $shop['username'],
            'message' => $item['message'],
            'remark' => $item['remark'],
            'order_express_info' => [
                'name' => $item['receiver'],
                'province' => ($item['provinceName']) ?? '',
                'city' => ($item['cityName']) ?? '',
                'area' => ($item['areaName']) ?? '',
                'address' => $item['receiverAddress'],
                'mobile' => $item['receiverMobile'],
                'trackingNumber' => ($detail[0]['subTrackingNumber']) ?? '',
                'expressName' => ($detail[0]['subExpressName']) ?? '',
                'status' => empty($detail[0]['subExpressStatus']) ? 100 : (($detail[0]['subExpressStatus'] == 5) ? 6 : $detail[0]['subExpressStatus']),
                'consignTime' => ($item['consignTime']) ?? '',
                'confirmTime' => ($item['confirmTime']) ?? '',
                'townCode' => '',
                'town' => ''
            ],
//            'order_refund_info' => empty($item['refundId'])?new \stdClass(): [
//                'refundId' => $item['refundId'],
//                'refundTime'=>'',
//                'refundType'=>'',
//                'refundStatus'=>$detail[0]['refundStatus'],
//                'productId'=>$detail[0]['productId'],
//                'skuId'=>$detail[0]['skuId'],
//                'refundAmount'=>''
//            ],
            'freight_amount' => $item['freightAmount'] * 100,
            'discount_amount' => empty($item['discountAmount']) ? '' : $item['discountAmount'] * 100,
            'platform_discount_amount' => '未提供',
            'business_discount_amount' => '未提供',
            'plat_promotion_discount_amount' => empty($item['platPromotionDiscountAmount']) ? '' : $item['platPromotionDiscountAmount'] * 100,
            'biz_promotion_discount_amount' => $item['bizPromotionDiscountAmount'] * 100,
            'plat_coupon_discount_amount' => $item['platCouponDiscountAmount'] * 100,
            'biz_coupon_discount_amount' => $item['bizCouponDiscountAmount'] * 100,
            'plat_red_packet_discount_amount' => $item['platRedPacketDiscountAmount'] * 100,
            'sku_code'=>empty($detail[0]['skuCode'])?'':str_replace(' ','',$detail[0]['skuCode']),
            'area' => $shop['area'],
            'uc_name' => $ucname,
            'id'=>$item['orderId']
        ];
        if($item['orderStatus']==4){
            $orderInfo['consign_time']=date('Y-m-d H:i:s');
        }
        foreach ($detail as $skuInfo) {
            $orderInfo['product_infos'][] = [
                'productId' => $skuInfo['productId'],
                'skuId' => '',
                'skuDesc' => $skuInfo['skuDesc'],
                'productUrl' => $skuInfo['pageOnlineUrl'],
                'productName' => $skuInfo['productName'],
                'productImage' => $skuInfo['commodityImage'],
                'originalPrice' => $skuInfo['sellPrice'],
                'buyNum' => $skuInfo['buyNum'],
                'actualPrice' => $skuInfo['sellPrice'],
                'discountAmount' => $skuInfo['discountAmount'],
                'authorId' => $skuInfo['authorId'],
                'authorName' => $skuInfo['authorName'],
                'ucName' => $skuInfo['ucName'],
                'planId' => $skuInfo['planId'],
                'planName' => $skuInfo['planName'],
                'unitId' => ($skuInfo['unitId'])??'',
                'unitName' => ($skuInfo['unitName'])??'',
                'ideaId' => ($skuInfo['ideaId'])??'',
                'ideaText' => ($skuInfo['ideaText'])??''
            ];
        }
        return $orderInfo;

    }

    /***
     * 发送发货信息到百度
     * @return void
     */
    public static function deliveryOrderToBaidu(){
        $params=[
            'page'=>1,
            'pageSize'=>1000,
            'where'=>[
                ['status','=',0],

            ],
            'order'=>['id asc'],
        ];
        $url = 'https://api.baidu.com/json/sms/service/PlatOrderBusinessService/deliverOrder';
        $list=OrderHistoryModel::getList($params);
        foreach ($list as $item){
            $info = ShopModel::getShopInfoByOrderId($item['order_id']);
            if(empty($info['shopInfo']['accesstoken']['accessToken']))
            {
                $message='订单店铺不存在或AccessToken异常';
                $is_success=0;
            }
            else
            {
                $data = [
                    'header' => [
                        'authorityType' => 5,
                        'userName' => $info['shopInfo']['username'],
                        'accessToken' => $info['shopInfo']['accesstoken']['accessToken']
                    ],
                    'body' => [
                        'orderId' => $item['order_id'],
                        'orderPackageInfos' => [
                            [
                                'trackingNumber' => $item['tracking_number'],
                                'expressName' => $item['express_name'],
                                'packageMemo' => $item['memo']
                            ]
                        ],
                        'appId' => 5
                    ],
                ];
                $header = [
                    'Content-Type: application/json'
                ];
                $res = json_decode(post($url, json_encode($data), $header));
                $message=($res)?((!empty($res->header)&&$res->header->desc=='success')?'操作成功':$res->header->failures[0]->message):'订单不存在';
                $is_success=($res->header->desc=='success')?1:0;
            }
            $item->save([
                'status'=>1,
                'reason'=> $message,
                'is_success'=>$is_success,
                'res'=>($res)??new \stdClass()
            ]);
        }
    }


}
